package dao

import (
	"fmt"
	"math"
	"order_srv/basic/config"
	"strings"
	"time"
)

// 订单统计结果结构体
type OrderStatisticsResult struct {
	OrderDate         string `json:"order_date"`          // 日期
	TotalOrderCount   int64  `json:"total_order_count"`   // 总订单总数
	UnpaidOrderCount  int64  `json:"unpaid_order_count"`  // 未支付订单总数
	InvalidOrderCount int64  `json:"invalid_order_count"` // 无效订单总数
	ValidOrderCount   int64  `json:"valid_order_count"`   // 有效订单总数
	RefundOrderCount  int64  `json:"refund_order_count"`  // 退款订单总数
}

// 按特定日期查询订单统计信息
func CountOrdersBySpecificDay(date string, orderType, payWay int64) (*OrderStatisticsResult, error) {
	result := &OrderStatisticsResult{
		OrderDate: date,
	}
	// 解析日期字符串为时间对象
	_, err := time.Parse("2006-01-02", date)
	if err != nil {
		return nil, fmt.Errorf("invalid date format: %w", err)
	}
	// 构建查询条件
	tx := config.DB.Table("orders").Where("DATE(create_at) = ?", date)

	// 如果orderType不为0，则添加订单类型过滤
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 如果payWay不为0，则添加支付方式过滤
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	// 查询总订单数
	var totalCount int64
	if err := tx.Count(&totalCount).Error; err != nil {
		return nil, err
	}
	result.TotalOrderCount = totalCount

	// 查询未支付订单数 (订单状态4)
	var unpaidCount int64
	if err := tx.Where("order_status = ?", 4).Count(&unpaidCount).Error; err != nil {
		return nil, err
	}
	result.UnpaidOrderCount = unpaidCount

	// 查询无效订单数 (订单状态6)
	var invalidCount int64
	if err := tx.Where("order_status = ?", 6).Count(&invalidCount).Error; err != nil {
		return nil, err
	}
	result.InvalidOrderCount = invalidCount

	// 查询有效订单数 (订单状态5)
	var validCount int64
	if err := tx.Where("order_status = ?", 5).Count(&validCount).Error; err != nil {
		return nil, err
	}
	result.ValidOrderCount = validCount

	// 查询退款订单数 (订单状态7)
	var refundCount int64
	if err := tx.Where("order_status = ?", 7).Count(&refundCount).Error; err != nil {
		return nil, err
	}
	result.RefundOrderCount = refundCount

	return result, nil
}

// parseDateTime 解析多种格式的日期时间字符串
func parseDateTime(dateStr string) (time.Time, error) {
	// 尝试多种常见的日期时间格式
	formats := []string{
		"2006-01-02",                // 基本日期格式
		"2006-01-02T15:04:05Z",      // ISO 8601 UTC
		"2006-01-02T15:04:05+08:00", // ISO 8601 带有时区
		"2006-01-02T15:04:05-0700",  // ISO 8601 另一种时区格式
	}

	for _, format := range formats {
		t, err := time.Parse(format, dateStr)
		if err == nil {
			return t, nil
		}
	}

	// 如果都失败，尝试使用 RFC3339 格式（更灵活）
	t, err := time.Parse(time.RFC3339, dateStr)
	if err == nil {
		return t, nil
	}

	return time.Time{}, fmt.Errorf("unable to parse date: %s", dateStr)
}

// GetChartOrderData 按日期范围查询订单类型统计数据（用于图表展示）
func GetChartOrderData(startDate, endDate string, orderType, payWay int64) ([]*OrderStatisticsResult, error) {
	var results []*OrderStatisticsResult
	// 解析开始日期（支持多种格式）
	startTime, err := parseDateTime(startDate)
	if err != nil {
		return nil, fmt.Errorf("invalid start date format: %w", err)
	}
	startDate = startTime.Format("2006-01-02") // 转换为标准日期格式用于SQL查询

	// 处理结束日期，如果为空则默认为当天
	var endTime time.Time
	if endDate == "" {
		endTime = time.Now()
		endDate = endTime.Format("2006-01-02")
	} else {
		endTime, err = parseDateTime(endDate)
		if err != nil {
			return nil, fmt.Errorf("invalid end date format: %w", err)
		}
		endDate = endTime.Format("2006-01-02") // 转换为标准日期格式用于SQL查询
	}

	// 检查开始时间是否晚于结束时间
	if startTime.After(endTime) {
		return nil, fmt.Errorf("start date must be before end date")
	}
	// 构建查询条件
	tx := config.DB.Table("orders").
		Select("DISTINCT DATE(create_at) AS date").
		Where("DATE(create_at) BETWEEN ? AND ?", startDate, endDate)

	// 如果orderType不为0，则添加订单类型过滤
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 如果payWay不为0，则添加支付方式过滤
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	// 查询日期范围内的所有日期
	var dates []string
	if err := tx.Order("date DESC").Scan(&dates).Error; err != nil {
		return nil, err
	}

	// 为每个日期统计订单信息
	for _, date := range dates {
		t, err := time.Parse(time.RFC3339, date)
		if err != nil {
			return nil, fmt.Errorf("unable to parse date: %s", date)
		}
		// 格式化时间为仅包含日期的字符串（格式为 2006-01-02）
		dateStr := t.Format("2006-01-02")
		dayResult, err := CountOrdersBySpecificDay(dateStr, orderType, payWay)
		if err != nil {
			return nil, err
		}
		results = append(results, dayResult)
	}

	return results, nil
}

// 按月统计订单数据
func GetMonthlyOrderData(startYearMonth, endYearMonth string, orderType, payWay int64) ([]*OrderStatisticsResult, error) {
	var results []*OrderStatisticsResult

	// 解析日期字符串为时间对象
	startTime, err := time.Parse("2006-01", startYearMonth)
	if err != nil {
		return nil, fmt.Errorf("invalid start date format: %w", err)
	}

	if endYearMonth == "" {
		endYearMonth = time.Now().Format("2006-01")
	}
	endTime, err := time.Parse("2006-01", endYearMonth)
	if err != nil {
		return nil, fmt.Errorf("invalid end date format: %w", err)
	}

	// 检查 startYearMonth 是否晚于 endYearMonth
	if startTime.After(endTime) {
		return nil, fmt.Errorf("start year month must be before end year month")
	}

	// 构建查询条件
	tx := config.DB.Table("orders").
		Select("DISTINCT DATE_FORMAT(create_at, '%Y-%m') AS month").
		Where("DATE_FORMAT(create_at, '%Y-%m') BETWEEN ? AND ?", startYearMonth, endYearMonth)

	// 如果orderType不为0，则添加订单类型过滤
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 如果payWay不为0，则添加支付方式过滤
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	// 查询年月范围内的所有月份
	var months []string
	if err := tx.Order("month ASC").Scan(&months).Error; err != nil {
		return nil, err
	}

	// 为每个月份统计订单信息
	for _, month := range months {
		// 创建月度统计结果
		monthResult := &OrderStatisticsResult{
			OrderDate: month, // 使用年月格式，如"2023-01"
		}

		// 构建该月份的查询条件
		monthTx := config.DB.Table("orders").Where("DATE_FORMAT(create_at, '%Y-%m') = ?", month)

		// 如果orderType不为0，则添加订单类型过滤
		if orderType != 0 {
			monthTx = monthTx.Where("order_type = ?", orderType)
		}

		// 如果payWay不为0，则添加支付方式过滤
		if payWay != 0 {
			monthTx = monthTx.Where("pay_way = ?", payWay)
		}

		// 查询该月总订单数
		var totalCount int64
		if err := monthTx.Count(&totalCount).Error; err != nil {
			return nil, err
		}
		monthResult.TotalOrderCount = totalCount

		// 查询该月未支付订单数 (订单状态4)
		var unpaidCount int64
		if err := monthTx.Where("order_status = ?", 4).Count(&unpaidCount).Error; err != nil {
			return nil, err
		}
		monthResult.UnpaidOrderCount = unpaidCount

		// 查询该月无效订单数 (订单状态6)
		var invalidCount int64
		if err := monthTx.Where("order_status = ?", 6).Count(&invalidCount).Error; err != nil {
			return nil, err
		}
		monthResult.InvalidOrderCount = invalidCount

		// 查询该月有效订单数 (订单状态5)
		var validCount int64
		if err := monthTx.Where("order_status = ?", 5).Count(&validCount).Error; err != nil {
			return nil, err
		}
		monthResult.ValidOrderCount = validCount

		// 查询该月退款订单数 (订单状态7)
		var refundCount int64
		if err := monthTx.Where("order_status = ?", 7).Count(&refundCount).Error; err != nil {
			return nil, err
		}
		monthResult.RefundOrderCount = refundCount

		results = append(results, monthResult)
	}

	return results, nil
}

// GetYearlyOrderData 按年统计订单数据
// startYear: 开始年份，格式为"YYYY"（如"2022"）
// endYear: 结束年份，格式为"YYYY"（如"2023"），为空时查询到当前年份
// 返回按年统计的订单数据，包含总订单数、未支付订单数、无效订单数、有效订单数和退款订单数
func GetYearlyOrderData(startYear, endYear string, orderType, payWay int64) ([]*OrderStatisticsResult, error) {
	var results []*OrderStatisticsResult

	// 解析日期字符串为时间对象
	startTime, err := time.Parse("2006", startYear)
	if err != nil {
		return nil, fmt.Errorf("invalid start date format: %w", err)
	}

	if endYear == "" {
		endYear = time.Now().Format("2006")
	}
	endTime, err := time.Parse("2006", endYear)
	if err != nil {
		return nil, fmt.Errorf("invalid end date format: %w", err)

	}
	// 检查 startYear 是否晚于 endYear
	if startTime.After(endTime) {
		return nil, fmt.Errorf("start year must be before end year")
	}

	// 构建查询条件
	tx := config.DB.Table("orders").
		Select("DISTINCT YEAR(create_at) AS year").
		Where("YEAR(create_at) BETWEEN ? AND ?", startYear, endYear)

	// 如果orderType不为0，则添加订单类型过滤
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 如果payWay不为0，则添加支付方式过滤
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	// 查询年份范围内的所有年份
	var years []string
	err = tx.Order("year DESC").Scan(&years).Error

	if err != nil {
		return nil, err
	}

	// 遍历每个年份，统计订单数据
	for _, year := range years {
		yearResult := &OrderStatisticsResult{
			OrderDate: year,
		}

		// 构建该年份的查询条件
		yearTx := config.DB.Table("orders").Where("YEAR(create_at) = ?", year)

		// 如果orderType不为0，则添加订单类型过滤
		if orderType != 0 {
			yearTx = yearTx.Where("order_type = ?", orderType)
		}

		// 如果payWay不为0，则添加支付方式过滤
		if payWay != 0 {
			yearTx = yearTx.Where("pay_way = ?", payWay)
		}

		// 查询该年份总订单数
		var totalCount int64
		if err = yearTx.Count(&totalCount).Error; err != nil {
			return nil, err
		}
		yearResult.TotalOrderCount = totalCount

		// 查询该年份未支付订单数 (订单状态1)
		var unpaidCount int64
		if err = yearTx.Where("order_status = ?", 1).Count(&unpaidCount).Error; err != nil {
			return nil, err
		}
		yearResult.UnpaidOrderCount = unpaidCount

		// 查询该年份无效订单数 (订单状态2)
		var invalidCount int64
		if err = yearTx.Where("order_status = ?", 2).Count(&invalidCount).Error; err != nil {
			return nil, err
		}
		yearResult.InvalidOrderCount = invalidCount

		// 查询该年份有效订单数 (订单状态5)
		var validCount int64
		if err = yearTx.Where("order_status = ?", 5).Count(&validCount).Error; err != nil {
			return nil, err
		}
		yearResult.ValidOrderCount = validCount

		// 查询该年份退款订单数 (订单状态7)
		var refundCount int64
		if err = yearTx.Where("order_status = ?", 7).Count(&refundCount).Error; err != nil {
			return nil, err
		}
		yearResult.RefundOrderCount = refundCount

		results = append(results, yearResult)
	}

	return results, nil
}

//   ————————————————————————————————订单平均金额————————————————————————————————————————

// 日均订单金额数据结构
type DayAvgAmountData struct {
	Date       string  `json:"date"`        // 日期
	AvgAmount  float64 `json:"avg_amount"`  // 平均订单金额
	OrderCount int     `json:"order_count"` // 订单数量
}

// GetDayAvgAmount 查询某日订单平均金额
// date 日期，格式为"YYYY-MM-DD"
// orderType 订单类型，1-实时单 2-预约单 3-接机单 4-送机单，0表示不筛选
// payWay 支付方式，1-支付宝 2-微信，0表示不筛选
// 返回该日期的订单平均金额
func GetDayAvgAmount(date string, orderType, payWay int64) (DayAvgAmountData, error) {
	var results DayAvgAmountData
	_, err := time.Parse("2006-01-02", date)
	if err != nil {
		return DayAvgAmountData{}, fmt.Errorf("invalid date format: %w", err)
	}
	// 构建查询
	query := config.DB.Table("orders").
		Select("DATE(create_at) as date, AVG(price) as avg_amount, COUNT(*) as order_count").
		Where("order_status = 5").
		Where("DATE(create_at) = ?", date)

	if orderType != 0 {
		query = query.Where("order_type = ?", orderType)
	}
	if payWay != 0 {
		query = query.Where("pay_way = ?", payWay)
	}

	err = query.Debug().Group("DATE(create_at)").Order("DATE(create_at) ASC").Scan(&results).Error
	if err != nil {
		return DayAvgAmountData{}, err
	}

	return results, nil
}

// CalculateRangeAvgAmount 按日期范围统计平均订单金额
// startDate 开始日期，格式为"YYYY-MM-DD"
// endDate 结束日期，格式为"YYYY-MM-DD"，如果为空则默认为当前日期
// orderType 订单类型，1-实时单 2-预约单 3-接机单 4-送机单，0表示不筛选
// payWay 支付方式，1-支付宝 2-微信，0表示不筛选
// 返回按日期分组的订单平均金额统计结果
func CalculateRangeAvgAmount(startTime, endTime string, orderType, payWay int64) ([]DayAvgAmountData, error) {
	var results []DayAvgAmountData
	// 解析日期字符串为时间对象
	start, err := time.Parse("2006-01-02", startTime)
	if err != nil {
		return nil, fmt.Errorf("invalid start date format: %w", err)
	}
	end, err := time.Parse("2006-01-02", endTime)
	if err != nil {
		return nil, fmt.Errorf("invalid end date format: %w", err)
	}
	// 检查 startTime 是否晚于 endTime
	if start.After(end) {
		return nil, fmt.Errorf("start date must be before end date")
	}

	if endTime == "" {
		endTime = time.Now().Format("2006-01-02")
	} else {
		_, err = time.Parse("2006-01-02", endTime)
		if err != nil {
			return nil, fmt.Errorf("invalid end date format: %w", err)
		}
	}

	// 构建查询
	query := config.DB.Table("orders").
		Select("DATE(create_at) as date, AVG(price) as avg_amount, COUNT(*) as order_count").
		Where("order_status = 5").
		Where("DATE(create_at) BETWEEN ? AND ?", startTime, endTime)

	if orderType != 0 {
		query = query.Where("order_type = ?", orderType)
	}
	if payWay != 0 {
		query = query.Where("pay_way = ?", payWay)
	}

	err = query.Debug().Group("DATE(create_at)").Order("DATE(create_at) ASC").Scan(&results).Error
	if err != nil {
		return nil, err
	}

	return results, nil
}

// GetAvgPriceByMonth 按月统计订单平均金额
// db gorm数据库连接
// startYearMonth 开始年月，格式为"YYYY-MM"
// endYearMonth 结束年月，格式为"YYYY-MM"，如果为空则默认为当前年月
// orderType 订单类型，1-实时单 2-预约单 3-接机单 4-送机单，0表示不筛选
// payWay 支付方式，1-支付宝 2-微信，0表示不筛选
// 返回按月分组的订单平均金额统计结果
func GetAvgPriceByMonth(startYearMonth, endYearMonth string, orderType, payWay int64) ([]DayAvgAmountData, error) {
	var results []DayAvgAmountData
	// 解析日期字符串为时间对象
	start, err := time.Parse("2006-01", startYearMonth)
	if err != nil {
		return nil, fmt.Errorf("invalid start date format: %w", err)
	}

	if endYearMonth == "" {
		endYearMonth = time.Now().Format("2006-01")
	}
	end, err := time.Parse("2006-01", endYearMonth)
	if err != nil {
		return nil, fmt.Errorf("invalid end date format: %w", err)
	}

	// 检查 startTime 是否晚于 endTime
	if start.After(end) {
		return nil, fmt.Errorf("start date must be before end date")
	}

	// 构建查询
	tx := config.DB.Table("orders").
		Select("DATE_FORMAT(create_at, '%Y-%m') as date, AVG(price) as avg_amount, COUNT(*) as order_count").
		Where("DATE_FORMAT(create_at, '%Y-%m') BETWEEN ? AND ?", startYearMonth, endYearMonth).
		Where("order_status = 5")

	// 添加订单类型筛选条件
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 添加支付方式筛选条件
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	// 执行查询
	tx = tx.Debug().Group("DATE_FORMAT(create_at, '%Y-%m')").
		Order("DATE_FORMAT(create_at, '%Y-%m') DESC").
		Scan(&results)

	if tx.Error != nil {
		return nil, tx.Error
	}

	return results, nil
}

// GetAvgPriceByYear 按年统计订单平均金额
// startYear 开始年份，格式为"YYYY"
// endYear 结束年份，格式为"YYYY"，如果为空则默认为当前年份
// orderType 订单类型，1-实时单 2-预约单 3-接机单 4-送机单，0表示不筛选
// payWay 支付方式，1-支付宝 2-微信，0表示不筛选
// 返回按年分组的订单平均金额统计结果
func GetAvgPriceByYear(startYear, endYear string, orderType, payWay int64) ([]DayAvgAmountData, error) {
	var results []DayAvgAmountData
	// 解析日期字符串为时间对象
	start, err := time.Parse("2006", startYear)
	if err != nil {
		return nil, fmt.Errorf("invalid start date format: %w", err)
	}

	if endYear == "" {
		endYear = time.Now().Format("2006")
	}
	end, err := time.Parse("2006", endYear)
	if err != nil {
		return nil, fmt.Errorf("invalid end date format: %w", err)

	}
	// 检查 startTime 是否晚于 endTime
	if start.After(end) {
		return nil, fmt.Errorf("start date must be before end date")
	}
	// 构建查询
	tx := config.DB.Table("orders").
		Select("DATE_FORMAT(create_at, '%Y') as date, AVG(price) as avg_amount, COUNT(*) as order_count").
		Where("DATE_FORMAT(create_at, '%Y') BETWEEN ? AND ?", startYear, endYear).
		Where("order_status = 5")

	// 添加订单类型筛选条件
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 添加支付方式筛选条件
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	// 执行查询
	tx = tx.Debug().Group("DATE_FORMAT(create_at, '%Y')").
		Order("DATE_FORMAT(create_at, '%Y') ASC").
		Scan(&results)

	if tx.Error != nil {
		return nil, tx.Error
	}

	return results, nil
}

// GetAvgPriceByWeek 按周统计订单平均金额
// startYearWeek 开始年份周，格式为"YYYY-WW"
// endYearWeek 结束年份周，格式为"YYYY-WW"，如果为空则默认为当前年周
// orderType 订单类型，1-实时单 2-预约单 3-接机单 4-送机单，0表示不筛选
// payWay 支付方式，1-支付宝 2-微信，0表示不筛选
// 返回按周分组的订单平均金额统计结果
func GetAvgPriceByWeek(startYearWeek, endYearWeek string, orderType, payWay int64) ([]DayAvgAmountData, error) {
	var results []DayAvgAmountData

	// 解析日期字符串为时间对象
	start, err := time.Parse("2006-01", startYearWeek)
	if err != nil {
		return nil, fmt.Errorf("invalid start date format: %w", err)
	}

	if endYearWeek == "" {
		endYearWeek = time.Now().Format("2006-01")
	}
	end, err := time.Parse("2006-01", endYearWeek)
	if err != nil {
		return nil, fmt.Errorf("invalid end date format: %w", err)
	}
	// 检查 startTime 是否晚于 endTime
	if start.After(end) {
		return nil, fmt.Errorf("start date must be before end date")
	}
	// 构建查询
	tx := config.DB.Table("orders").
		Select("CONCAT(YEAR(create_at), '-', LPAD(WEEK(create_at), 2, '0')) as date, AVG(price) as avg_amount, COUNT(*) as order_count").
		Where("CONCAT(YEAR(create_at), '-', LPAD(WEEK(create_at), 2, '0')) BETWEEN ? AND ?", startYearWeek, endYearWeek).
		Where("order_status = 5")

	// 添加订单类型筛选条件
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 添加支付方式筛选条件
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	// 执行查询
	tx = tx.Debug().Group("CONCAT(YEAR(create_at), '-', LPAD(WEEK(create_at), 2, '0'))").
		Order("CONCAT(YEAR(create_at), '-', LPAD(WEEK(create_at), 2, '0')) ASC").
		Scan(&results)

	if tx.Error != nil {
		return nil, tx.Error
	}

	return results, nil
}

// ————————————————————————————增长率————————————————————————————————

// 两小时订单统计数据结构
type TwoHourOrderCount struct {
	TimeSlot   string // 时间段，如：00:00-02:00
	OrderCount int64  // 订单数量
}

// GetTwoHourOrderCounts 查询指定日期内每两小时的订单数量
// date: 查询日期，格式为"2006-01-02"
// orderType: 订单类型，0表示所有类型
// payWay: 支付方式，0表示所有方式
func GetTwoHourOrderCounts(date string, orderType, payWay int64) ([]*TwoHourOrderCount, error) {
	var results []*TwoHourOrderCount

	// 解析日期字符串
	dateTime, err := time.Parse("2006-01-02", date)
	if err != nil {
		return nil, fmt.Errorf("invalid date format: %w", err)
	}

	// 生成当天的开始时间（00:00:00）和结束时间（23:59:59）
	start := time.Date(dateTime.Year(), dateTime.Month(), dateTime.Day(), 0, 0, 0, 0, dateTime.Location())
	end := time.Date(dateTime.Year(), dateTime.Month(), dateTime.Day(), 23, 59, 59, 0, dateTime.Location())

	// 生成两小时的时间槽
	timeSlots := generateTwoHourTimeSlots(start, end)

	// 为每个时间槽查询订单数量
	for _, slot := range timeSlots {
		// 解析时间槽的开始和结束时间
		startTime, endTime, err := parseTimeSlot(slot, date)
		if err != nil {
			continue
		}

		// 构建查询条件
		tx := config.DB.Table("orders").Where("create_at BETWEEN ? AND ?", startTime, endTime)

		// 如果orderType不为0，则添加订单类型过滤
		if orderType != 0 {
			tx = tx.Where("order_type = ?", orderType)
		}

		// 如果payWay不为0，则添加支付方式过滤
		if payWay != 0 {
			tx = tx.Where("pay_way = ?", payWay)
		}

		// 查询订单数量
		var count int64
		if err := tx.Count(&count).Error; err != nil {
			return nil, err
		}

		// 添加到结果中
		results = append(results, &TwoHourOrderCount{
			TimeSlot:   slot,
			OrderCount: count,
		})
	}

	return results, nil
}

// parseTimeSlot 解析时间段字符串为时间对象
// date: 日期，格式为"2006-01-02"
func parseTimeSlot(timeSlot string, date string) (time.Time, time.Time, error) {
	// 分割时间段字符串
	parts := strings.Split(timeSlot, "-")
	if len(parts) != 2 {
		return time.Time{}, time.Time{}, fmt.Errorf("invalid time slot format")
	}

	// 使用传入的日期
	dateStr := date

	// 解析开始时间
	startTimeStr := dateStr + " " + parts[0] + ":00"
	startTime, err := time.Parse("2006-01-02 15:04:05", startTimeStr)
	if err != nil {
		return time.Time{}, time.Time{}, err
	}

	// 解析结束时间
	endTimeStr := dateStr + " " + parts[1] + ":00"
	endTime, err := time.Parse("2006-01-02 15:04:05", endTimeStr)
	if err != nil {
		return time.Time{}, time.Time{}, err
	}

	return startTime, endTime, nil
}

// generateTwoHourTimeSlots 生成两小时的时间槽
func generateTwoHourTimeSlots(start, end time.Time) []string {
	var slots []string

	// 将开始时间调整到两小时的边界

	adjustedStart := start.Truncate(time.Hour * 2)

	// 如果调整后的时间小于开始时间，增加两小时
	if adjustedStart.Before(start) {
		adjustedStart = adjustedStart.Add(time.Hour * 2)
	}

	// 生成时间槽直到结束时间
	current := adjustedStart
	for current.Before(end) || current.Equal(end) {
		// 计算当前时间段的结束时间
		next := current.Add(time.Hour * 2)

		// 生成时间段字符串
		startHour := current.Format("15:04")
		endHour := next.Format("15:04")
		slot := fmt.Sprintf("%s-%s", startHour, endHour)
		slots = append(slots, slot)

		// 移动到下一个时间段
		current = next
	}

	return slots
}

// ————————————————————————————复购统计————————————————————————————————

// 用户复购数据结构
// 用于记录每个用户的首次订单时间、后续订单时间和复购次数

type UserPurchaseData struct {
	UserId          uint32      `json:"user_id"`          // 用户ID
	FirstOrderTime  time.Time   `json:"first_order_time"` // 首次订单时间
	OrderTimes      []time.Time `json:"order_times"`      // 所有订单时间（按时间排序）
	RepurchaseCount int64       `json:"repurchase_count"` // 复购次数（总订单数-1）
}

// GetUserPurchaseData 获取指定条件的用户复购数据
// startTime 开始时间，格式为：2023-01-01 00:00:00
// endTime 结束时间，格式为：2023-01-01 23:59:59
// orderType 订单类型，1-实时单 2-预约单 3-接机单 4-送机单，0表示不筛选
// payWay 支付方式，1-支付宝 2-微信，0表示不筛选
// 返回用户复购数据列表
func GetUserPurchaseData(startTime, endTime string, orderType, payWay int64) ([]*UserPurchaseData, error) {
	var results []*UserPurchaseData
	// 解析时间字符串
	start, err := time.Parse("2006-01-02", startTime)
	if err != nil {
		return nil, fmt.Errorf("invalid start time format: %w", err)
	}

	end, err := time.Parse("2006-01-02", endTime)
	if err != nil {
		return nil, fmt.Errorf("invalid end time format: %w", err)
	}

	// 检查开始时间是否晚于结束时间
	if start.After(end) {
		return nil, fmt.Errorf("start time must be before end time")
	}

	// 先获取符合条件的用户ID列表
	tx := config.DB.Table("orders").
		Select("user_id").
		Where("create_at BETWEEN ? AND ?", start, end).
		Group("user_id")

	// 如果orderType不为0，则添加订单类型过滤
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 如果payWay不为0，则添加支付方式过滤
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	var userIds []uint32
	if err := tx.Scan(&userIds).Error; err != nil {
		return nil, err
	}

	// 为每个用户获取复购数据
	for _, userId := range userIds {
		userData, err := getUserPurchaseDetail(userId, start, end, orderType, payWay)
		if err != nil {
			// 如果单个用户获取失败，跳过该用户，继续处理其他用户
			continue
		}
		results = append(results, userData)
	}

	return results, nil
}

// getUserPurchaseDetail 获取单个用户的复购详情
// userId 用户ID
// start, end 时间范围
// orderType 订单类型，0表示不筛选
// payWay 支付方式，0表示不筛选
// 返回单个用户的复购数据
func getUserPurchaseDetail(userId uint32, start, end time.Time, orderType, payWay int64) (*UserPurchaseData, error) {
	userData := &UserPurchaseData{
		UserId:     userId,
		OrderTimes: make([]time.Time, 0),
	}

	// 构建查询条件
	tx := config.DB.Table("orders").
		Select("create_at").
		Where("user_id = ?", userId).
		Where("create_at BETWEEN ? AND ?", start, end).
		Order("create_at ASC")

	// 如果orderType不为0，则添加订单类型过滤
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 如果payWay不为0，则添加支付方式过滤
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	// 查询该用户的所有订单创建时间
	var orderTimes []time.Time
	if err := tx.Scan(&orderTimes).Error; err != nil {
		return nil, err
	}

	// 如果用户有订单
	if len(orderTimes) > 0 {
		userData.FirstOrderTime = orderTimes[0]               // 首次订单时间
		userData.OrderTimes = orderTimes                      // 所有订单时间
		userData.RepurchaseCount = int64(len(orderTimes) - 1) // 复购次数 = 总订单数 - 1
	}

	return userData, nil
}

// GetRepurchaseRate 计算指定条件下的复购率
// startTime 开始时间，格式为：2023-01-01 00:00:00
// endTime 结束时间，格式为：2023-01-01 23:59:59
// orderType 订单类型，1-实时单 2-预约单 3-接机单 4-送机单，0表示不筛选
// payWay 支付方式，1-支付宝 2-微信，0表示不筛选
// 返回复购率（有复购行为的用户数 / 总用户数）
func GetRepurchaseRate(startTime, endTime string, orderType, payWay int64) (float64, error) {
	// 获取用户复购数据
	userPurchaseData, err := GetUserPurchaseData(startTime, endTime, orderType, payWay)
	if err != nil {
		return 0, err
	}

	// 计算有复购行为的用户数（复购次数 >= 1）
	totalUsers := len(userPurchaseData)
	if totalUsers == 0 {
		return 0, nil // 没有用户数据时，复购率为0
	}

	repurchaseUsers := 0
	for _, userData := range userPurchaseData {
		if userData.RepurchaseCount >= 1 {
			repurchaseUsers++
		}
	}

	// 计算复购率
	repurchaseRate := float64(repurchaseUsers) / float64(totalUsers)
	return repurchaseRate, nil
}

// 时间间隔复购数据结构
type RepurchaseIntervalData struct {
	Interval string // 复购时间间隔（如：2天内，7天内等）
	Count    int64  // 该时间间隔内复购的用户数
}

// GetRepurchaseByInterval 按时间间隔统计复购人数
// startTime 开始时间，格式为：2023-01-01
// endTime 结束时间，格式为：2023-01-01
// orderType 订单类型，1-实时单 2-预约单 3-接机单 4-送机单，0表示不筛选
// payWay 支付方式，1-支付宝 2-微信，0表示不筛选
// 返回按时间间隔统计的复购人数列表
func GetRepurchaseByInterval(startTime, endTime string, orderType, payWay int64) ([]*RepurchaseIntervalData, error) {
	// 解析时间字符串

	if endTime == "" {
		endTime = time.Now().Format("2006-01-02")

	}

	start, err := time.Parse("2006-01-02", startTime)
	if err != nil {
		return nil, fmt.Errorf("invalid start time format, expected '2006-01-02': %w", err)
	}

	end, err := time.Parse("2006-01-02", endTime)
	if err != nil {
		return nil, fmt.Errorf("invalid end time format, expected '2006-01-02': %w", err)
	}
	if start.After(end) {
		return nil, fmt.Errorf("start date must be before end date")
	}
	// 获取用户复购数据
	userPurchaseData, err := GetUserPurchaseData(startTime, endTime, orderType, payWay)
	if err != nil {
		return nil, err
	}

	// 定义时间间隔
	intervals := []struct {
		name string
		days int
	}{{
		name: "2天内",
		days: 2,
	}, {
		name: "7天内",
		days: 7,
	}, {
		name: "15天内",
		days: 15,
	}, {
		name: "30天内",
		days: 30,
	}}

	// 初始化结果数组
	results := make([]*RepurchaseIntervalData, len(intervals))
	for i, interval := range intervals {
		results[i] = &RepurchaseIntervalData{
			Interval: interval.name,
			Count:    0,
		}
	}

	// 统计每个用户的复购间隔
	for _, userData := range userPurchaseData {
		// 至少有两次订单才有复购
		if len(userData.OrderTimes) < 2 {
			continue
		}

		// 获取首次订单时间
		firstOrder := userData.OrderTimes[0]

		// 检查后续订单是否在各个时间间隔内
		for i := 1; i < len(userData.OrderTimes); i++ {
			orderTime := userData.OrderTimes[i]
			// 计算与首次订单的时间差
			duration := orderTime.Sub(firstOrder)
			days := int(duration.Hours() / 24)

			// 更新对应时间间隔的计数
			for j, interval := range intervals {
				if days <= interval.days {
					results[j].Count++
					// 一旦在某个时间间隔内找到复购，就不再检查更小的间隔
					break
				}
			}
		}
	}

	return results, nil
}

// 购买转化分析数据结构
type PurchaseConversionData struct {
	Date               string  // 日期
	NewUserCount       int64   // 新注册用户数
	ConvertedUserCount int64   // 产生购买行为的用户数
	ConversionRate     float64 // 转化率
}

// GetPurchaseConversionData 获取购买转化分析数据
// startTime 开始时间，格式为：2023-01-01
// endTime 结束时间，格式为：2023-01-01
// businessType 业务类型，1-行程班线
// orderType 订单类型，1-实时单 2-预约单 3-接机单 4-送机单，0表示不筛选
// payWay 支付方式，1-支付宝 2-微信，0表示不筛选
// 返回购买转化分析数据列表
func GetPurchaseConversionData(startTime, endTime string, orderType, payWay int64) ([]*PurchaseConversionData, error) {
	// 参数验证
	if startTime == "" {
		return nil, fmt.Errorf("startTime and endTime cannot be empty")
	}
	if endTime == "" {
		endTime = time.Now().Format("2006-01-02")
	}

	// 解析时间字符串
	start, err := time.Parse("2006-01-02", startTime)
	if err != nil {
		return nil, fmt.Errorf("invalid start time format, expected '2006-01-02': %w", err)
	}

	end, err := time.Parse("2006-01-02", endTime)
	if err != nil {
		return nil, fmt.Errorf("invalid end time format, expected '2006-01-02': %w", err)
	}

	// 验证时间范围
	if start.After(end) {
		return nil, fmt.Errorf("startTime cannot be later than endTime")
	}

	// 限制时间范围，最多查询90天数据
	daysDiff := int(end.Sub(start).Hours()/24) + 1
	if daysDiff > 90 {
		return nil, fmt.Errorf("time range cannot exceed 90 days")
	}

	// 获取时间范围内的所有日期
	dates := make([]string, 0, daysDiff)
	current := start
	for current.Before(end) || current.Equal(end) {
		dates = append(dates, current.Format("2006-01-02"))
		current = current.AddDate(0, 0, 1)
	}
	// 初始化结果数组
	results := make([]*PurchaseConversionData, 0, len(dates))

	// 遍历每一天，计算转化数据
	for _, date := range dates {
		// 计算日期的起始和结束时间
		dateStart := date + " 00:00:00"
		dateEnd := date + " 23:59:59"

		// 获取当天新注册的用户数
		newUserCount, err := getNewUserCount(dateStart, dateEnd)
		if err != nil {
			return nil, fmt.Errorf("failed to get new user count for %s: %w", date, err)
		}

		// 获取当天有购买行为的用户数
		convertedUserCount, err := getConvertedUserCount(dateStart, dateEnd, orderType, payWay)
		if err != nil {
			return nil, fmt.Errorf("failed to get converted user count for %s: %w", date, err)
		}

		// 计算转化率，保留两位小数
		conversionRate := 0.0
		if newUserCount > 0 {
			conversionRate = math.Round(float64(convertedUserCount)/float64(newUserCount)*10000) / 100
		}

		// 添加到结果中
		results = append(results, &PurchaseConversionData{
			Date:               date,
			NewUserCount:       newUserCount,
			ConvertedUserCount: convertedUserCount,
			ConversionRate:     conversionRate,
		})
	}

	return results, nil
}

// getNewUserCount 获取特定时间范围内新注册的用户数
func getNewUserCount(startTime, endTime string) (int64, error) {
	var count int64
	// 从用户服务获取新注册用户数
	// 由于需要跨服务调用，这里简化处理，实际实现需要调用用户服务
	// 假设用户表在order_srv中可以访问
	err := config.DB.Table("user").
		Where("user_register_time BETWEEN ? AND ?", startTime, endTime).
		Where("user_role = ?", 1). // 1表示乘客角色
		Count(&count).Error

	return count, err
}

// getConvertedUserCount 获取特定时间范围内有购买行为的用户数
func getConvertedUserCount(startTime, endTime string, orderType, payWay int64) (int64, error) {
	// 构建查询条件
	tx := config.DB.Table("orders").
		Select("DISTINCT user_id").
		Where("create_at BETWEEN ? AND ?", startTime, endTime).
		Where("order_status = ?", 5) // 5表示已完成的订单

	// 如果orderType不为0，则添加订单类型过滤
	if orderType != 0 {
		tx = tx.Where("order_type = ?", orderType)
	}

	// 如果payWay不为0，则添加支付方式过滤
	if payWay != 0 {
		tx = tx.Where("pay_way = ?", payWay)
	}

	// 获取有购买行为的用户数量
	var count int64
	err := tx.Count(&count).Error

	return count, err
}
